package com.lcf.app.awss3.demo;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Console;
import cn.hutool.core.util.IdUtil;
import cn.hutool.http.*;
import cn.hutool.system.SystemUtil;
import com.alibaba.fastjson.JSON;
import com.amazonaws.HttpMethod;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.*;
import org.springframework.http.MediaType;
import org.springframework.http.MediaTypeFactory;

import java.io.File;
import java.net.URL;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class Demo {

    private static final String ACCESS_KEY = "minioadmin";
    private static final String SECRET_KEY = "minioadmin";
    private static final String ENDPOINT = "http://192.168.254.18:9000";

    public static void main(String[] args) {
        AmazonS3 amazonS3 = AmazonS3ClientBuilder
                .standard()
                .withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(ENDPOINT, ""))
                .withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials(ACCESS_KEY, SECRET_KEY)))
                .build();
        // 查询桶列表
        List<Bucket> buckets = amazonS3.listBuckets();
        String bucketNames = buckets.stream().map(Bucket::getName).collect(Collectors.joining(" ; ", " [ ", " ] "));
        Console.log("bucketNames : {}", bucketNames);

        // 创建桶
        String bucketName = "s3-bucket";
        if (!amazonS3.doesBucketExistV2(bucketName)) { // 不存在则创建
            Bucket bucket = amazonS3.createBucket(bucketName);
        }
        // 存储
        File file = new File("D:/qrcode.jpg");
        amazonS3.putObject(new PutObjectRequest(bucketName, file.getName(), file));
        boolean b = amazonS3.doesObjectExist(bucketName, file.getName());
        Console.log("文件是否存在：{}", b);

        // 下载并生成新文件
        amazonS3.getObject(new GetObjectRequest(bucketName, file.getName()), new File("D:/qrcode-new.jpg"));

        // 删除文件
        amazonS3.deleteObject(bucketName, file.getName());
        boolean b1 = amazonS3.doesObjectExist(bucketName, file.getName());
        Console.log("文件是否存在：{}", b1);

        // 生成临时上传地址
        GeneratePresignedUrlRequest request =
                new GeneratePresignedUrlRequest(bucketName, IdUtil.fastSimpleUUID() + ".jpg", HttpMethod.PUT)
                        .withExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 10)); // 10分钟后失效
        //request.addRequestParameter("", "");
        URL URL = amazonS3.generatePresignedUrl(request);
        Console.log("URL:{}", URL);

        // 使用临时地址上传文件（可以避免上传文件浪费后端资源）
        HttpRequest httpRequest = HttpUtil.createRequest(Method.PUT, URL.toString());
        httpRequest.header(Header.CONTENT_TYPE, "application/octet-stream");
        httpRequest.body(FileUtil.readBytes(file));
        HttpResponse execute = httpRequest.execute();
        /*Console.log("httpRequest:{}", httpRequest);*/
        Console.log("execute : {}", execute);


        /************************* 分片上传  ************************/

        // https://blog.csdn.net/weixin_44359036/article/details/126514643
        String fileName = "D:/my_application/PDManer-win_v4.5.1.zip";
        File zipFile = new File(fileName);
        String key = zipFile.getName();
        // 1: 初始化分片上传任务
        ObjectMetadata objectMetadata = new ObjectMetadata();
        String contentType = MediaTypeFactory.getMediaType(fileName).orElse(MediaType.APPLICATION_OCTET_STREAM).toString();
        objectMetadata.setContentType(contentType);
        InitiateMultipartUploadRequest initiateMultipartUploadRequest =
                new InitiateMultipartUploadRequest(bucketName, key).withObjectMetadata(objectMetadata);
        InitiateMultipartUploadResult initiateMultipartUploadResult = amazonS3.initiateMultipartUpload(initiateMultipartUploadRequest);
        String uploadId = initiateMultipartUploadResult.getUploadId();

        // 2：分片上传
        long partSize = 10 * 1024 * 1024; // Set part size to 10 MB. 分片不能小于5M
        long filePosition = 0;
        long fileSize = zipFile.length();
        for (int i = 1; filePosition < fileSize; i++) { // 这里内部可以并发执行
            partSize = Math.min(partSize, (fileSize - filePosition));
            UploadPartRequest uploadRequest = new UploadPartRequest()
                    .withBucketName(bucketName)
                    .withKey(key)
                    .withUploadId(uploadId)
                    .withPartNumber(i)
                    .withFileOffset(filePosition)
                    .withFile(zipFile)
                    .withPartSize(partSize);
            UploadPartResult uploadPartResult = amazonS3.uploadPart(uploadRequest);
            Console.log("uploadPartResult: {}", JSON.toJSONString(uploadPartResult));
            filePosition += partSize;
        }

        // 3: 合并
        // 查询分片数据
        PartListing listParts = amazonS3.listParts(
                new ListPartsRequest(bucketName, key, uploadId));
        List<PartETag> tagList = listParts.getParts()
                .stream()
                .map(v -> new PartETag(v.getPartNumber(), v.getETag())).collect(Collectors.toList());
        // 分片上传完成后任务完成接口
        amazonS3.completeMultipartUpload(new CompleteMultipartUploadRequest()
                .withBucketName(bucketName)
                .withKey(key)
                .withPartETags(tagList)
                .withUploadId(uploadId));
    }

}
